package org.funsciencewithyourcomputer.client;

import java.util.HashSet;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.Timer;

public class Dictionary {

	HashSet<String> words = new HashSet<String>();

	String[] wordsArray = null;

	String data;
	
	Steg listener;
	
	int wordStart = 0;
	
	int wordCount = 0;
	
	Timer parsingTimer = new Timer() {
		public void run() {
			if (data == null)
				return;
			if (wordsArray == null) {
				// Get the number of words in the french or english dictionary
				int size = NLS.get(NLS.DICTIONARY).equals(NLS.DICTIONARY[1]) ? 58259 : 53901;
				wordsArray = new String[size];
			}
			while (true) {
				int wordEnd = data.indexOf('\r', wordStart + 1);
				if (wordEnd == -1)
					break;
				String word = data.substring(wordStart, wordEnd);
				words.add(word);
				wordsArray[wordCount] = word;
				wordStart = wordEnd + 2; // also skip '\n'
				wordCount++;
				if (wordCount % 10000 == 0) {
					Steg.setStatus(NLS.get(NLS.PROGRESS_DICTIONARY, new Object[] {wordCount}), false);
					// time to let the UI do some work
					parsingTimer.schedule(100);
					return;
				}
			}
			data = null;
			listener.dictionaryLoaded();
		}
	};
	
	public void read(Steg listener) {
		this.listener = listener;
		DictionaryLoading.readDictionary(this);
	}
	
	public void setWords(String data) {
		this.data = data;
		parsingTimer.schedule(1000);
	}

	public String createRandomLine(int[] lettersCount, Score score) {
//		if (true)
//			return "abcabcs"; // TEST
		String result = "";
		for (int count : lettersCount) {
			String word = getRandomWord(count);
			score.addHiddenWord(word);
			result += word;
		}
		return shuffle(result);
	}

	public static String replace(String string, int index, String replacement) {
		return string.substring(0, index) + replacement
				+ string.substring(index + 1, string.length());
	}

	public String shuffle(String string) {
		String result = "";
		while (string.length() > 0) {
			int index = Random.nextInt(string.length());
			result = result + string.charAt(index);
			string = string.substring(0, index) + string.substring(index + 1);
		}
		return result;
	}

	public String getRandomWord() {
		return wordsArray[Random.nextInt(wordsArray.length)];
	}

	public String getRandomWord(int nLetters) {
		while (true) {
			String word = getRandomWord();
			if (word.length() == nLetters) {
				return word;
			}
		}
	}

	public boolean isWord(String letters) {
		return words.contains(letters);
	}

	/**
	 * Return the indeces of given letters in given line. If not all letters
	 * exist uniquely in line, return null.
	 * Also return the resulting line with all corresponding indeces replaced with space.
	 */
	public static int[] getPositions(String line, String word, String[] resultingLine) {
		resultingLine[0] = line;
		if (word.length() == 0 || word.contains(" "))
			return null;
		int[] result = new int[word.length()];
		int i = 0;
		for (char letter : word.toCharArray()) {
			result[i] = line.indexOf("" + letter);
			if (result[i] == -1)
				return null;
			line = replace(line, result[i], " ");
			i++;
		}
		resultingLine[0] = line;
		// Check if word can be found multiple times
		int[] result2 = getPositions(line, word, resultingLine);
		if (result2 != null) {
			int[] result3 = new int[result.length+result2.length];
			System.arraycopy(result, 0, result3, 0, result.length);
			System.arraycopy(result2, 0, result3, result.length, result2.length);
			result = result3;
		}
		return result;
	}

	public String removeWord(String line, String word) {
		for (char letter : word.toCharArray()) {
			line = line.replaceFirst("" + letter, " ");
		}
		return line;
	}
}
